<template>
    <div class="pb-3">
        <input
            v-if="tagType === 'input'"
            type="text"
            class="form-control"
            :class="{ 'is-invalid': inputRef.error }"
            v-model="inputRef.val"
            @blur="validateInput"
            @input="handleInput"
            v-bind="$attrs"
        />
        <textarea
            v-else
            cols="30"
            rows="10"
            class="form-control"
            :class="{ 'is-invalid': inputRef.error }"
            v-model="inputRef.val"
            @blur="validateInput"
            @input="handleInput"
            v-bind="$attrs"
        ></textarea>
        <span class="invalid-feedback" v-if="inputRef.error">{{ inputRef.message }}</span>
    </div>
</template>

<script lang="ts">
import { defineComponent, onMounted, onUnmounted, PropType, reactive } from "vue";
import { emitter } from "./ValidateForm.vue";
export interface RulesProp {
    type: "required" | "email" | "custom";
    message: string;
    validator?: () => boolean;
}
type TagType = "input" | "textarea";
export default defineComponent({
    props: {
        rules: {
            type: Array as PropType<RulesProp[]>,
            default: () => [],
        },
        modelValue: String,
        tagType: {
            type: String as PropType<TagType>,
            default: "input",
        },
    },
    inheritAttrs: false,
    setup(props, { emit, attrs }) {
        const inputRef = reactive({
            val: props.modelValue || "",
            error: false,
            message: "",
        });
        const validateInput = () => {
            let isPassed = false;
            const emailReg = /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;
            let isAllPassed = props.rules.every(item => {
                switch (item.type) {
                    case "required":
                        isPassed = inputRef.val.trim() != "";
                        inputRef.message = item.message;
                        break;
                    case "email": 
                        isPassed = emailReg.test(inputRef.val);
                        inputRef.message = item.message;
                        break;
                    case "custom":
                        isPassed = item.validator ? item.validator() : true;
                        inputRef.message = item.message;
                        break;
                    default:
                        inputRef.error = false;
                        break;
                }
                return isPassed;
            });
            inputRef.error = !isAllPassed;
            return isAllPassed;
        };
        const handleInput = (e: KeyboardEvent) => {
            emit("update:modelValue", (e.target as HTMLInputElement).value);
        };
        const clearInput = () => {
            inputRef.val = "";
        };
        emitter.emit("form-item-created", validateInput);
        emitter.on("form-item-clear", clearInput);
        onUnmounted(() => {
            emitter.off("form-item-clear", clearInput);
        });
        return {
            inputRef,
            validateInput,
            handleInput,
        };
    },
});
</script>

<style lang="scss" scoped></style>
